package com.apes.scm.masterdata.frame.model;

import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.DefaultPersistListener;
import com.apes.framework.jpa.Model;
import com.apes.framework.jpa.Name;
import com.apes.framework.jpa.audit.Auditing;
import com.apes.framework.jpa.comment.Comment;
import com.apes.framework.jpa.generator.ApesGenerator;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.scm.masterdata.enumeration.model.Enumeration;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.party.model.PartySerialNumber;
import com.apes.scm.masterdata.party.repository.PartySerialNumberRepository;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.annotations.SelectBeforeUpdate;

import javax.persistence.*;
import javax.validation.constraints.NotNull;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 功能：部门信息
 *
 * @author HuJianlin
 * @create 2018-03-17 16:00
 */
@Auditing
@Getter
@Setter
@SelectBeforeUpdate
@DynamicInsert
@DynamicUpdate
@Entity
@EntityListeners(DefaultPersistListener.class)
@Table(name = "mas_dept")
public class Dept extends Model {

    @Id
    @Column(name = "id", length = 30)
    @Comment("部门编码")
    @ApesGenerator(code = "mas_dept_sequence", name = "业务部门", padding = 3)
    private String id;  //部门编码

    @Name
    @Column(name = "name", nullable = false, length = 120)
    @Comment("部门名称")
    private String name; //部门名称

    @NotNull
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "company_id", referencedColumnName = "id")
    @Comment("所属公司")
    private PartyRole company; //所属公司

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "branch_id", referencedColumnName = "id")
    @Comment("行政部门编码")
    private Branch branch;  //行政部门编码

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "cost_center_id", referencedColumnName = "id")
    @Comment("成本中心")
    private DutyCenter costCenterId;  //成本中心

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "profit_center_id", referencedColumnName = "id")
    @Comment("利润中心")
    private DutyCenter profitCenterId;  //利润中心

//    @Name
//    @ManyToOne(fetch = FetchType.LAZY)
//    @JoinColumn(name = "dept_type", referencedColumnName = "id")
//    @Comment("部门类型")
//    private Enumeration deptType; //部门类型（businessClass）（BC_purchase：采购; BC_sale：销售; BC_other：其他）

    @ElementCollection
    @CollectionTable(name = "mas_dept_type", joinColumns = @JoinColumn(name = "dept_id"))
    @MapKeyColumn(name = "id")
    @Column(name = "name")
    private Map<String, String> deptTypes;

    public boolean existDeptType(DeptEnum deptType){
        return this.getDeptTypes().containsKey(deptType.getDeptType());
    }

    public Map<String, String> getDeptTypes() {
        if (deptTypes == null && deptTypeList != null) {
            deptTypes = new HashMap<>();
            for (Object o : deptTypeList) {
                Map<String, String> m = (Map<String, String>) o;
                deptTypes.put(m.get("id"), m.get("name"));
            }
        }
        return deptTypes;
    }

    @Transient
    private List deptTypeList;

    public List<Map<String, String>> getDeptTypeList() {
        if (deptTypeList == null && deptTypes != null) {
            deptTypeList = new ArrayList<>();
            for (Map.Entry<String, String> entry : deptTypes.entrySet()) {
                if ("this".equals(entry.getKey())) continue;
                Map<String, String> map = new HashMap<>();
                map.put("id", entry.getKey());
                map.put("name", entry.getValue());
                deptTypeList.add(map);
            }
        }
        return deptTypeList;
    }

    public void addDeptType(DeptEnum deptEnum) {
        if (deptTypeList == null) deptTypeList = new ArrayList<>();
        Map<String, String> map = new HashMap<>();
        map.put("id", deptEnum.getDeptType());
        map.put("name", deptEnum.getMsg());
        deptTypeList.add(map);
    }

    @Name
    @Column(name = "ORIGIN", length = 20)
    @Comment("外部ID")
    private String origin; //外部ID

    @Column(name = "valid", nullable = false, columnDefinition = "number(1,0) default 1")
    @Comment("有效标记")
    private boolean valid = true; //有效

    @Column(name = "to_old_flag", nullable = false, columnDefinition = "number(1,0) default 1")
    @Comment("转旧框架做单标记")
    private boolean toOldFlag = false; //false表示不转

    @Column(name = "inner_tag", nullable = false, columnDefinition = "number(1,0) default 0")
    @Comment("内定标记")
    private boolean innerTag = false;

    /**
     * 获取部门编码
     *
     * @param dept
     * @return
     */
    public String obtainDeptId(Dept dept) {
        if (SpringManager.getBean(PartySerialNumberRepository.class).findAll(JpaDsl.toCriteriaByEq("companyId", dept.getCompany().getId())).size() == 0) {
            throw new RuntimeException(String.format("公司[%s][%s]不存在于公司维度自增编码流水号记录表，无法生产新的部门编码，请检查公司是否存在！", dept.getCompany().getId(), dept.getCompany().getName()));
        }
        //获取部门编码
        PartySerialNumber serialNumber = SpringManager.getBean(PartySerialNumberRepository.class).
                findOne(JpaDsl.toCriteriaByEq("companyId", dept.getCompany().getId())).orElse(new PartySerialNumber());
        serialNumber.setCompanyId(Integer.parseInt(dept.getCompany().getId()));
        serialNumber.setName(dept.getCompany().getParty().getName());
        serialNumber.setOperation(dept.getCompany().getParty().getCorporate().getOperation());
        //部门编码+1后保存
        int deptId = serialNumber.getDeptId() + 1;
        serialNumber.setDeptId(deptId);
        serialNumber = SpringManager.getBean(PartySerialNumberRepository.class).saveAndFlush(serialNumber);
        return dept.getCompany().getId() + String.format("%3d", serialNumber.getDeptId()).replace(" ", "0");
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Dept dept = (Dept) o;
        return id.equals(dept.id);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id);
    }
}
